package ltd.dujiabao.capability.adapter.driven.persistence.capmng;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

import lombok.extern.slf4j.Slf4j;
import ltd.dujiabao.capability.domain.capmng.sync.Predicate;
import ltd.dujiabao.capability.domain.capmng.sync.Puller;
import ltd.dujiabao.capability.domain.capmng.sync.Transferor;
import ltd.dujiabao.capability.domain.capmng.sync.Worker;
import ltd.dujiabao.capability.domain.capmng.sync.WorkerRepository;
import ltd.dujiabao.capability.domain.devmng.DevType;

/**
 * @author : DuJiabao
 * @Project : ddd-capability
 * @Time : 2024/4/9 21:39
 * @Desc :
 */
@Component
@Slf4j
public class WorkerRepositoryImpl implements WorkerRepository, ApplicationListener<CapabilityChangedEvent> {
    private final CapabilityProperties capabilityProperties;

    private final ApplicationContext applicationContext;

    private volatile Map<DevType, List<Worker>> workerMap = new HashMap<>();

    @Autowired
    public WorkerRepositoryImpl(CapabilityProperties capabilityProperties, ApplicationContext applicationContext) {
        this.capabilityProperties = capabilityProperties;
        this.applicationContext = applicationContext;
    }

    @PostConstruct
    public void refresh() {
        Map<DevType, List<Worker>> workerMap = new HashMap<>();
        for (CapabilityProperties.SynchronizerProperties prop : capabilityProperties.getSynchronizers()) {
            List<Worker> workers = new ArrayList<>();
            for (CapabilityProperties.WorkerProperties workerProp : prop.getWorkers()) {
                Predicate predicate = applicationContext.getBean(workerProp.getPredicate());
                Puller puller = applicationContext.getBean(workerProp.getPuller());
                Transferor transferor = applicationContext.getBean(workerProp.getTransferor());
                Worker worker = new Worker(LocalDateTime.now(), 0L, predicate, puller, transferor);
                workers.add(worker);
            }
            for (DevType devType : prop.getDevTypes()) {
                workerMap.put(devType, workers);
            }
        }
        this.workerMap = workerMap;
        log.info("Finish refresh WorkerRepositoryImpl.");
    }

    @Override
    public List<Worker> findWorkers(DevType devType) {
        return workerMap.get(devType);
    }

    @Override
    public void onApplicationEvent(CapabilityChangedEvent event) {
        refresh();
    }
}
